/**
 * WTF Engine
 * 
 * License... etc.
 **
 * WTF Dev Console
 * 	(part of WTF GUI)
 **
 * Authors: Sean Micklethwaite, Mac Duy Hai
 */

#include "gui_console.h"
#include "gui_layout.h"
#include "scripting.h"
#include <iostream>

using namespace WtfGui;
using namespace WtfEngine;

Console::tRef Console::grActiveConsole;

Console::Console(): Window(" ..::: wtfConsole 0.2a :::...") {
	// Create font
	tFont::tRef fConsolas = new tFont("v_gui_consoleFont", "media/fonts/consolas");
	
	// Create Label
	mLabel = new Widgets::Label("Command:", fConsolas);
	mLabel->ExpandToText();
	
	
	// Create input
	mInput = new Widgets::InputField(fConsolas);
	mInput->Resize(0, 20);
	
	// Create log
	mLog = new Widgets::LogField(25, fConsolas);
	
	// Add to Window
	AddChild(mLabel);
	AddChild(mInput);
	AddChild(mLog);
	
	// Widgets Layout
	new AdvancedLayout(mLabel->getLayout(),
		AdvancedLayout::Default(), AdvancedLayout::PositionAfter(mLog->getLayout()),
		AdvancedLayout::Default(), AdvancedLayout::Default());
	new AdvancedLayout(mInput->getLayout(),
		AdvancedLayout::PositionAfter(mLabel->getLayout()), AdvancedLayout::PositionAfter(mLog->getLayout()),
		new AdvancedLayout::InnerSizeOf(this->getLayout(), new AdvancedLayout::Subtract(new AdvancedLayout::SizeOf(mLabel->getLayout()))), AdvancedLayout::Default());
	new AdvancedLayout(mLog->getLayout(),
		AdvancedLayout::Default(), AdvancedLayout::Default(),
		new AdvancedLayout::InnerSizeOf(this->getLayout()), AdvancedLayout::InnerSizeAdd(this->getLayout(), -20));

	// Set window layout
	Move(20,20);
	Resize(500,500);

	// Welcome message
	mLog->Dump(" *** Welcome to WTF Developer's Console. ***");
	mLog->Dump("     Type your commands and press enter");
	mLog->Dump("       Use Ctrl+W/A/S/D for navigation.");
	mLog->Dump(" ");
};



/**
 * Console Keypress Handler. Pipe commands to the Input Field and/or update
 * the Log Field as appropriate.
 * TODO: The enter key press is currently handled here. Logically (and ideally)
 * it should be handled inside the Input Field, which will then raise an appropriate
 * event.
 */
bool Console::OnKeyPress(int k, int flags) {
	/* START PREVIOUS IMPLEMENTATION
	switch(k){
		case '\b':
			mpBody->sCommand = mpBody->sCommand.substr(0, mpBody->sCommand.length() - 1);
			break;
		case '\r':
			if(mpBody->sCommand == "cls"){
				mpBody->sTextBuf = "";
			}else{
				try{
					mpBody->sTextBuf = mpBody->sTextBuf + "> " + mpBody->sCommand + '\r';
					ScriptHost::GetInstance().EvalScript(mpBody->sCommand.c_str());
				}catch(const std::exception& e){
					mpBody->sTextBuf = mpBody->sTextBuf + e.what() + '\r';
				};
			};
			
			mpBody->sCommand = "";
			break;
		default:
			mpBody->sCommand += (char)k;
	}; END PREVIOUS IMPLEMENTATION */
	
	// Keypress logger
	// std::cout << "Keycode: " << k << std::endl;
	
	switch (k) {
		case '\r':
			// Execute
			Execute(mInput->getText());
		
			// Push to history and empty input
			mInput->PushHistory();
			mInput->setText("");
			return true;
		default:
			return mInput->OnKeyPress(k, flags);
	}
};

/// Recognizes some internal commands, otherwise pass execution to Scripting
void Console::Execute(const String& command) {
	if (command == "clear") {
		mLog->Clear();
	} else {
		// Scripting
		mLog->Dump("] ");
		mLog->Append(command);
		
		try {
			ScriptHost::GetInstance().EvalScript(command);
		} catch(const std::exception& e) {
			mLog->Dump(e.what());
		};
	}
};
